package com.example.yx.demo16;

import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

public class A16 {
    public static void main(String[] args) throws NoSuchMethodException {
        /*
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        //根据方法名字筛选
        pointcut.setExpression("execution(* foo())");
        //原理:根据名字判断是否匹配正确到指定的方法
        System.out.println(pointcut.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println(pointcut.matches(T1.class.getMethod("bar"), T1.class));

        //根据方法注解筛选
        pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
        System.out.println(pointcut.matches(T2.class.getMethod("foo"), T2.class));
        System.out.println(pointcut.matches(T1.class.getMethod("bar"), T1.class));

         */

        StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() {


            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                //检查方法上是否加了指定注解
                MergedAnnotations annotations = MergedAnnotations.from(method);
                if (annotations.isPresent(Transactional.class)){
                    return true;
                }
                //检查类上是否有指定注解
                annotations = MergedAnnotations.from(targetClass);
                if (annotations.isPresent(Transactional.class)) {
                    return true;
                }
                //检查接口上是否有指定注解
                annotations = MergedAnnotations.from(targetClass,MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if (annotations.isPresent(Transactional.class)) {
                    return true;
                }
                return false;
            }
        };

        System.out.println(pointcut.matches(T2.class.getMethod("foo"), T2.class));
        System.out.println(pointcut.matches(T3.class.getMethod("foo"),T3.class));
    }

    static class T1 {
        @Transactional
        public void foo(){}

        public void bar(){}
    }

    @Transactional
    static class T2{
        public void foo(){}
    }

    @Transactional
    interface I3{
        void foo();
    }

    static class T3 implements I3 {
        @Override
        public void foo() {

        }
    }

}
